/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.support.scripting.cmd;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.contexts.ReportContext;
import cn.easyplatform.dos.FieldDo;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.lang.Streams;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.support.scripting.AbstractScriptCmd;
import cn.easyplatform.support.scripting.ScriptCmdContext;
import cn.easyplatform.type.FieldType;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRRtfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.oasis.JROdsExporter;
import net.sf.jasperreports.engine.export.oasis.JROdtExporter;
import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter;
import net.sf.jasperreports.engine.export.ooxml.JRPptxExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.export.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class ReportCmd extends AbstractScriptCmd {

    private ReportContext rc;

    public ReportCmd(ScriptCmdContext scc, ReportContext rc) {
        super(scc);
        this.rc = rc;
    }

    public RecordContext create() {
        return rc.create();
    }

    public void load(Object... args) {
        StringBuilder sb = new StringBuilder();
        if (args.length == 0) {
            for (String name : rc.getIds().split(","))
                sb.append(scc.getTarget().getValue(name));
        } else {
            for (Object obj : args)
                sb.append(obj);
        }
        List<FieldDo> params = new ArrayList<FieldDo>();
        FieldDo fd = new FieldDo(FieldType.VARCHAR);
        fd.setValue(rc.getEntityId());
        fd.setName("reportid");
        params.add(fd);
        fd = new FieldDo(FieldType.VARCHAR);
        fd.setValue(sb.toString());
        fd.setName("bizid");
        params.add(fd);
        FieldDo obj = scc
                .getCommandContext()
                .getBizDao()
                .selectObject(
                        "select content from sys_report_log where reportid=? and bizid=?",
                        params);
        if (obj != null)
            rc.setPrint((Serializable) SerializationUtils
                    .deserialize((byte[]) obj.getValue()));
        else
            rc.setPrint(null);
    }

    public String export(String type, String filename) {
        ByteArrayOutputStream bos = null;
        FileWriter fw = null;
        try {
            JasperPrint jasperPrint = (JasperPrint) rc.getPrint();
            String contentType = null;
            if (type.equalsIgnoreCase("pdf")) {
                JRPdfExporter exporter = new JRPdfExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/pdf";
            } else if (type.equalsIgnoreCase("csv")) {
                JRCsvExporter exporter = new JRCsvExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleWriterExporterOutput exporterOutput = new SimpleWriterExporterOutput(
                        bos = new ByteArrayOutputStream(), "utf-8");
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleCsvExporterConfiguration configuration = new SimpleCsvExporterConfiguration();
                    configuration.setFieldDelimiter(",");
                    configuration.setRecordDelimiter(";\r\n");
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/octet-stream";
            } else if (type.equalsIgnoreCase("rtf")) {
                JRRtfExporter exporter = new JRRtfExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleWriterExporterOutput exporterOutput = new SimpleWriterExporterOutput(
                        bos = new ByteArrayOutputStream(), "utf-8");
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleRtfReportConfiguration configuration = new SimpleRtfReportConfiguration();
                    configuration.setIgnoreHyperlink(true);
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "text/rtf";
            } else if (type.equalsIgnoreCase("odt")) {
                JROdtExporter exporter = new JROdtExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleOdtExporterConfiguration configuration = new SimpleOdtExporterConfiguration();
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/vnd.oasis.opendocument.text";
            } else if (type.equalsIgnoreCase("ods")) {
                JROdsExporter exporter = new JROdsExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleOdsExporterConfiguration configuration = new SimpleOdsExporterConfiguration();
                    configuration.setCreateCustomPalette(true);
                    configuration.setKeepWorkbookTemplateSheets(true);
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/vnd.oasis.opendocument.spreadsheet";
            } else if (type.equalsIgnoreCase("xls")) {
                JRXlsExporter exporter = new JRXlsExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleXlsExporterConfiguration configuration = new SimpleXlsExporterConfiguration();
                    configuration.setCreateCustomPalette(true);
                    configuration.setKeepWorkbookTemplateSheets(true);
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/vnd.ms-excel";
            } else if (type.equalsIgnoreCase("xlsx")) {
                JRXlsxExporter exporter = new JRXlsxExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleXlsxExporterConfiguration configuration = new SimpleXlsxExporterConfiguration();
                    configuration.setCreateCustomPalette(true);
                    configuration.setKeepWorkbookTemplateSheets(true);
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            } else if (type.equalsIgnoreCase("docx")) {
                JRDocxExporter exporter = new JRDocxExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimpleDocxExporterConfiguration configuration = new SimpleDocxExporterConfiguration();
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            } else if (type.equalsIgnoreCase("pptx")) {
                JRPptxExporter exporter = new JRPptxExporter();
                exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
                SimpleOutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(
                        bos = new ByteArrayOutputStream());
                try {
                    exporter.setExporterOutput(exporterOutput);
                    SimplePptxExporterConfiguration configuration = new SimplePptxExporterConfiguration();
                    exporter.setConfiguration(configuration);
                    exporter.exportReport();
                } finally {
                    exporterOutput.close();
                    exporterOutput = null;
                    exporter = null;
                }
                contentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
            }
            CommandContext cc = scc.getCommandContext();
            String format = cc.getProjectService().getConfig()
                    .getString("dateFormat");
            if (Strings.isBlank(format))
                format = "yyyyMMdd";
            filename = filename.replace("&dt", DateFormatUtils.format(new Date(), format));
            filename = cc.getRealPath(filename);

            OutputStream os = null;
            try {
                os = new BufferedOutputStream(new FileOutputStream(new File(filename)));
                IOUtils.write(bos.toByteArray(), os);
            } catch (Exception e) {
                throw new EasyPlatformWithLabelKeyException(
                        "script.engine.cmd.file", filename);
            } finally {
                IOUtils.closeQuietly(os);
            }
            return filename;
        } catch (Exception ex) {
            throw new EasyPlatformWithLabelKeyException("report.export.error",
                    ex, rc.getId(), type);
        } finally {
            Streams.safeClose(bos);
            Streams.safeClose(fw);
        }
    }

    public void save(Object... args) {
        StringBuilder sb = new StringBuilder();
        if (args.length == 0) {
            for (String name : rc.getIds().split(","))
                sb.append(scc.getTarget().getValue(name));
        } else {
            for (Object obj : args)
                sb.append(obj);
        }
        List<FieldDo> params = new ArrayList<FieldDo>();
        CommandContext cc = scc.getCommandContext();
        if (rc.getState() == 'C') {
            FieldDo fd = new FieldDo(FieldType.VARCHAR);
            fd.setValue(rc.getEntityId());
            fd.setName("reportid");
            params.add(fd);
            fd = new FieldDo(FieldType.VARCHAR);
            fd.setValue(sb.toString());
            fd.setName("bizid");
            params.add(fd);
            fd = new FieldDo(FieldType.BLOB);
            fd.setValue(SerializationUtils.serialize(rc.getPrint()));
            fd.setName("content");
            params.add(fd);
            fd = new FieldDo(FieldType.DATETIME);
            fd.setValue(new Date());
            fd.setName("createdate");
            params.add(fd);
            fd = new FieldDo(FieldType.VARCHAR);
            fd.setValue(scc.getTarget().getParameter("720"));
            fd.setName("createuser");
            params.add(fd);
            cc.getBizDao()
                    .update(cc.getUser(),
                            "insert into sys_report_log(reportid,bizid,content,createdate,createuser) values(?,?,?,?,?)",
                            params, true);
        } else if (rc.getState() == 'U') {
            FieldDo fd = new FieldDo(FieldType.BLOB);
            fd.setValue(SerializationUtils.serialize(rc.getPrint()));
            fd.setName("content");
            params.add(fd);
            fd = new FieldDo(FieldType.DATETIME);
            fd.setValue(new Date());
            fd.setName("updatedate");
            params.add(fd);
            fd = new FieldDo(FieldType.VARCHAR);
            fd.setValue(scc.getTarget().getParameter("720"));
            fd.setName("updateuser");
            params.add(fd);
            fd = new FieldDo(FieldType.VARCHAR);
            fd.setValue(rc.getEntityId());
            fd.setName("reportid");
            params.add(fd);
            fd = new FieldDo(FieldType.VARCHAR);
            fd.setValue(sb.toString());
            fd.setName("bizid");
            params.add(fd);
            cc.getBizDao()
                    .update(cc.getUser(),
                            "update sys_report_log set content=?,updatedate=?,updateuser=? where reportid=? and bizid=?",
                            params, true);
        }
    }
}
